//
//  ReadMe.swift
//  01-公司开发介绍
//
//  Created by teacher on 16/7/19.
//  Copyright © 2016年 teacher. All rights reserved.
//
/*
    - 上课版本
    - readMe 文件
        - 作用: 
                - 把一些重要的东西记录说明下 便于后期我们在开发该项目能回忆起来
                - 为了你高薪飞 交接工作
                - 能叫大家清晰的知道我今天做了什么 便于你们晚自习复习

 =========================================================================
 
 -第十二天 微博数据缓存


    - 保存首页数据分析
        - 当前首页数据是列表数据
            - 建议使用FMDB保存
        - 保存那些数据
            - statusid (下拉刷新 或者上拉加载更多 需要通过sinceid 和maxid)
            - userid (同一个手机 两个登录 使用微博缓存数据 需要区分出 谁的微博数据)
            - status (微博数据 字典-Swift) 需要转成 NSData
            - createtime  (当用户缓存数据的时候 得到一个时间)


















 
        - 新浪微博缓存数据库的表的字段
             - statusid: 该微博的id, 是一个主键
             - status: 该条微博的 JSON 数据
             - userid: 这条微博属于哪个用户 也成为主键，区分两个用户加载回来同一条数据的情况
             - 如果有多个帐号，都要缓存数据，那么如果不区别某些数据是属于哪个帐号的话，那么在没网的情况下去数据库加载数据的话，那么数据就会错乱
             - 还有一个点需要注意：A 用户有一条微博的id是 1234 ，用户B 也关注了 id 为1234这条微博的作者，那么就会出现：主键相同，userid不同，解决方法就是将userid也作为主键，也就是将 statusid和userid作为复合主键
             
             - 新浪微博的数据库缓存可能会存在什么问题
             - 数据不完整：如果用户在已经有一些缓存数据的情况下，关注了很多用户，但是客户端现在每次加载数据都是从本地去加载，那么，可能关注的用户的微博数据就加载不出来
             - 数据的安全问题：比如有一个用户发了一条违规的微博，这个时候，我们在新浪没有删除这条微博之前就把这条微博给缓存到本地了，那么如果从本地去读取数据的话，就会每次把这条违规的微博加载出来
             - 比如某条微博的转发量是1000，缓存到本地，数据可能不是最真实的
 
 
 
         - 不适合缓存
             - 一些实效性比较高的数据
             - 一些敏感度较高的数据
         
         - 可以缓存什么样的数据
             - 固定变化不大的数据，并且数据的敏感度不高的数据
             
             - 如果使用数据库缓存，一定要记得清理缓存
             
         
         - 清除缓存
             - 清除缓存的操作一定不要交给用户去做
             - SQLite的数据缓存一定要定时去清理，因为SQLite数据库，清除数据之后，数据库文件大小不会变，因为 sqlite 预估你文件的大小，那么sqlite会保留空间（这样设计是为了尽量少的文件进行扩容操作）
             - SD会自动清除7天以上的图片数据
 


=========================================================================
 
    - 第十一天 图文混排

        - 下午内容回顾
            - 发布微博
                - 文字微博
                - 图片&文字微博
            - 发布文字的时候 里面有图片表情
                - 遍历composeTextView 富文本 
                    - 当遍历到我们自定义的文本附件 得到其身上的emoticon 
                        - 通过的到chs 
                - 把遍历的结果拼接字符串
            - 发送系统通知 隐藏或者显示占位问题
            - 强制调用代理方法 改变右侧按钮的状态
            - 使用RegexKitLite 遍历字符串 匹配我们的正则结果
                - 通过匹配到的结果 在单例中遍历一位数组 得到对象的emoticon


        - 上午内容回顾
            - 创建20个表情按钮
                - 把表情按钮添加到数组中
                - 设置按钮的frame    
                - 删除按钮 和frame
                - cell 中的字控件微调
            - pageView 给pageViewCell 赋值
                - 先把20个按钮全部隐藏
                - 遍历 模型一位数组 给button赋值
                    - emoji表情
                    - 图片表情
            - 添加pageControl
                - 使用kvc  currentPageImage  pageImage
            - 使用通知 
                - 层级比较深  使用通知
            - emoji表情上屏 
            - 图片表情上屏
                    - 文本附件
                        - 设置image
                        - 设置bounds


=========================================================================

    - 第十天 表情键盘

        - 第十天内容回顾
            - 读取emoticon.bundle 文件
                - 读取plist文件
                - 字典转模型 得到一位数组
                - 通过 页数 做一位数组 转二维数组
                - 使用一位数组二维得到三维数组组
            - 使用三维数组 给表情键盘提供数据
            - 点击底部视图中的按钮 滚动pageView
                - 设置default按钮为选中状态
            - 滚动pageView  切换 底部视图按钮的选中状态
                - 注意 tag = 0  不要使用

        - 为什么使用bundle文件
            

        - 上午内容回顾
            - 通过监听系统通知 监听键盘将要该表frame 
                - 监听 UIKeyboardFrameEndUserInfoKey y值 
                - 更新底部视图的bottom约束
            - 自定义表情键盘
                - 使用textView.inputView  
                - 判断 inputView 是否为nil
                - 判断是否是表情键盘 更改底部视图按钮的image
            - 自定义表情键盘中的底部视图
                - UIStackView 
                    - 不需要再给子控件设置约束 或者frame
                    - 只支持 9.0 以上
                    - 设置axis  排列方向
                    - 设置distribution 填充方式
                    - 初始化的时候 一定要加上frame
                    - 通过addArrangedSubview 添加子空间
                - 添加按钮点击事件 闭包回调


=========================================================================

    - 第九天 撰写动画
        - 下午内容回顾
            - 命名空间
            - 通过字符串获取class   类名.Type
            - class 传入的格式  "项目名.类名" 《自定义类》
            - uiimagepickerControler
            - 自定义配图cell 
                - 添加背景图片
                - 添加删除按钮
            - 压缩图片 (通过等比例压缩   通过上下文 完成图片压缩)

        - 图片问题
            - 会引起内存暴涨
            - 会消耗用户流量
            - 会影响你上传图片的速度
            -解决办法
                - 图片压缩

        - 上传图片流程
            - 客户端上传图片
                - 压缩图片
                - 上传压缩后的图片到服务器
            - 通过客户端上传的图片
                - 01 保存原图
                - 02 通过自己的方式对客户端的上传的图片进行处理 变成高清图

        - 上午内容回顾
            - 自定义composeView
                    - 截屏
                    - 设置磨砂效果
                    - 自定义button
                        - 对imageView 和tilte 重新设置frame 和imageView & title的相关属性设置
                    - 读取plist文件 
                        - 字典转模型
                    - 遍历数组添加按钮
                    - 给按钮设置动画
                        - 通过第三方框架pop 动画

        - pop页面 分析
            - 贴在哪里 -> mainVc
            - 磨砂效果 怎么搞
                    - 对当前屏幕截屏 获得image  然后通过苹果的分类搞定
                    - 创建6个按钮 （因为image 和title 显示的位置不是默认的而且没有高亮效果, 需要自定义）



=========================================================================

    - 第八天 时间格式化、发布微博界面
            - 回顾上午学习的内容
                    - 微博来源 
                            - 使用字符串的截取
                                - 富文本的使用
                    - 底部视图
                            - 转发 评论 赞 
                            - 字符串的替换
                    - 微博时间格式化

            - 微博时间格式化处理

                - 如果是今年

                    - 如果是今天
                        - 小于60秒 显示 刚刚
                        - 大于等于60秒且小于3600秒  显示 xx分钟前
                        - 大于等于3600秒  显示  xx小时前

                    - 如果是昨天
                        - 例如 2016-07-25 10:10:10  显示格式 昨天 10:10

                    - 如果是其他
                        - 例如 2016-05-01 10:10:10  显示格式 05月01日 10:10

                - 如果不是今年
                    - 例如 2015-01-01 10:10:10
                        - 显示 格式: 2015年01月01日 10:10








            - 转发 评论 赞 业务逻辑处理
                - 如果count <= 0  显示 转发 评论 赞 例如 0  显示 转发 评论 赞
                - 如果count > 0
                    - 如果 count < 10000  数据是多少显示多少  例如  8888  显示 8888
                    - 如果 count >= 10000  显示 x.x万       例如 12000  显示 1.2 万
                            - 注意 如果 count%10000 = 0  显示  例如 20000 显示 2万


==========================================================================
    - 第七天 配图和下拉刷新
        - 自定义下拉刷新控件分析
            - 自定义控件添加到tableView身上
                - frame = 0,-50,屏幕的宽度,50
            - 分析
            - 当用户拖动tableView 而且没有松手
                - 当contentOffset.y > -114 显示正常
                - 当contentOffset.y <= -114 下拉中
            - 当用户拖动tableView 而且松手了
                -  如果当前的状态为 下拉中   ---》刷新中

        - 上午内容回顾
            - 自定义配图 （collectionView）
            - 给status 添加一个属性 pic_urls 数组 需要程序员手动数组转模型数组
            - 通过外界给配图赋值 的数组.count  决定配图的size
                    -col count == 4 ? 2 : count>=3 ? 3: count
                    -row count == 4 ? 2 : (count -1)/3 + 1
            - 原创微博
                - 通过pic_urls.count 判断是否显示配图
                    - 有配图
                    - 没有配图
                - 系统cell
                - 自定义cell
                - 给cell赋值
                    - bgImageView
                    - gifImageView
            - 转发微博
                - retweet_status.pic_urls
                - 同原创微博相同
            - 抽取cell中常用间距


==========================================================================

    - 第六天 首页cell布局
        - 首页布局分析
                - 使用tableView显示
                - 由于是列表 每条微博数据 使用cell显示
                    - 原创微博
                        - 头像
                        - 昵称
                        - 会员等级
                        - 认证
                        - 微博发布时间
                        - 微博来源
                        - 微博内容
                        - 配图(可能存在 可能不存在)

                    - 转发微博 （可能存在, 可能不存在）
                        - 微博内容
                        - 配图(可能存在 可能不存在)

                    - 底部视图
                        - 转发按钮
                        - 评论按钮
                        - 赞按钮

        - 上午学习的内容回顾
            - 搭建UI
            - 请求首页数据
                - 01 使用网络工具类来请求（公共请求方法）
                - 02 把请求方法抽取到网络请求工具类中
                - 03 把请求抽取到StatusListViewModel
            - 创建模型
                - SHStatus
            - 自定义cell
                - 原创微博
                    - 头像
                    - 昵称
                    - 微博等级
                    - 时间
                    - 来源
                    - 认证
                    - 微博内容未做

            - 创建SHUser
                    - 由于系统不能给我们自定义的模型赋值 
                        - 重写setValueForKey 判断如果key == “user” 需要程序员手动赋值
                        - 其他交给系统
            - 创建StatusViewModel(为cell服务 主要做数据处理)

            
            - ViewModel逻辑
                - homeVc -> statusListViewModel -> networkTools
                - statusList - > statusViewModel -> status -> cell
            - 今日内容总结
                - 请求首页数据
                - 抽取statusListViewModel
                - 创建模型
                - 搭建UI
                - cell分析(原创 转发 底部视图)
                - 开发原创视图
                - User
                - 抽取出一个statusViewModel
                - 对原创微博其他的控件赋值
                - 添加原创微博的正文
                - 底部视图
                - 转发微博

==========================================================================

    - 第五天 获取用户信息，界面跳转
        - 内容预告
            - 获取accessToken
            - 获取用户信息
            - 日期格式转换
            - 通过归档解档保存用户信息
            - 搭建欢迎界面
            - 使用通知切换根控制器
            - 搭建新特性界面
            - 判断是否是最新版本

        - 用户首次登陆
                - 访客视图界面
                - 调到微博登陆界面
                - 完成授权和保存数据后
                - 跳到欢迎界面
                
                - 当用户显示完欢迎界面后  
                - 完成后显示MainVc
        - 关于根控制器确定
                - 如果用户已经登录  rootVc -> WelcomeVc
                - 如果用户没有登录  rootVc -> MainVc



        - 首次启动app
            - 判断用户是否登录
                - 如果登录了 
                    rootVc = WelComeVc
                - 如果没有登录
                    rootVc = MainVc


            - 当用户没有登录
                - MainVc
                - 点击注册或者登录按钮 -> OAuthVc -> 完成授权和保存数据
                - 发送通知  显示WelComeVc
                - welComeVc 发送通知 把其当前的根控制器切换成MainVc
            - 当用户已经登录了
                - rootVc = WelComeVc
                - 当欢迎界面动画完成后 发送通知 切换根控制器为MainVc

            - 当用户进入新特性页面
                - 当用户滑动到最后一页 
                - 点击button
                    - 发送通知 切换根控制器 为MainVc

            - 判断版本
                - 为什么判断版本
                    - 因为为了显示新特性页面
                - 什么时候会显示新特性界面
                    - 如果用户已经登录了
                            - 如果是新版本
                                    - rootVc = NewFeature
                            - 如果不是新版本
                                    - rootVc = WelcomeVc
                    - 如果用户没有登录
                                    - rootVc = MainVc

            
            - 第五天 下午内容回顾
                - 给ViewModel 中 添加 accessToken isLogin
                - 欢迎界面 
                        - 阻尼动画
                        - 切换根控制器
                - 新特性页面
                        - 阻尼动画
                        - 切换根控制器
                - 判断app版本
                        - 设置根控制器
                - 自定义搜索框


==========================================================================


    - 第四天
        - Extension的抽取
            - UIImageView
            - UILabel
        - Common 与OC中的pch文件相似
            - 屏幕的宽高 
            - RGB颜色
            - 随机颜色
            - 主题颜色
        - 回顾OC单例
        - 学习了Swift单例的写法（与Swift中的懒加载相似）
            - 一共有两种写法
        - OC和Swift项目分别使用 对应的类
                - 如果OC中使用Swift的类    
                    - 格式 import "项目名-Swift.h"
                - 如果Swift中使用OC的类
                    - 创建桥接文件  #import "OC类.h"
        - OC中 AFN 网络访问工具类的封装
        - Swift中的 AFN 网络访问工具类的封装
                - 网络请求公共的方法
                    - 分别请求不同接口的方法
                        - 作用
                            - 便于后期维护管理
                            - 把请求的urlString 和请求参数 均写在网络请求工具类中
        - OAuth授权
            - OAuth  open auth  开放的授权
                - 为什么使用该方式登录？
                        - 如果一个公司开发一个app 使用手机号码完成注册登录 该公司可能没有职业道德
                            - 泄露用户信息
                        - 方便 微博账号 微信账号 等等
                            - 公司大 认知度大 
                        - 模拟器 无法使用sdk 方式 为了给大家讲解 那么就需要使用OAuth
                        - 我们做的一个是第三方的微博（山寨的）    
                            - 如果我们想使用微博的接口和数据 那么我们开发者就得遵守协议
                - OAuth授权
                        - 01 需要开发者在微博开发者平台 注册一个账号 open.weibo.com
                        - 02 需要注册为开发者 （个人开发者 公司开发者）
                        - 03 在新浪微博开发者平台 注册一个应用
                                - 只有注册完成 新浪微博会生成一个appKey appSecret （与人的身份证相似）
                                        - appKey 当前应用的id 
                                            作用: 加载webView页面和请求其他接口需要
                                        - appSecret 请求接口需要
                                - 需要开发者设置回调页
                                        -  加载webView页面和请求其他接口需要
                                - 需要开发者设置测试账号
                                        - 当前的app为上架  但是开发者需要开发测试 就需要添加测试账号
                                        - 会加多个 (老板或者头或者产品经理)
                        - 04 通过新浪微博提供的webView urlString 拼接appKey和回调页 加载授权界面
                        - 05 用户使用中 输入用户名和密码 点击确定
                        - 06 点击授权按钮  完成授权
                        - 07 得到微博服务器返回的code （授权码）
                        - 08 通过上面的相关信息 获取 accessToken
                        - 09 通过accessToken  获取个人信息和访问其他接口


                - 关于注册问题
                    - 注册
                            - 01  http://www.baidu.com?company="xxxx"&手机号=12345678&密码=1234567
                                    - 如果请求成功 服务器 userid name 相关信息 表示出当前用户是使用手机注册
                            - 02  http://www.baidu.com?company="open"&userid=xxx&name="xxx"&sex="0"&age="18" 表示当前用户使用第三方信息完成注册

                - 第四天内容回顾
                    - 搭建OAuth界面
                    - OAuth授权
                            
                        - 登录开发者平台
                        - 注册一个应用
                                - 得到appKey appSecret 回调页
                                - 设置回调页
                                - 添加测试账号
                        - 加载webView 页面
                        - 通过webView 代理方法 得到code （code的截取）


==========================================================================



    - 第三天 项目阶段

        - 公司组织开发架构
            - 客户 -> 甲方
            - 老板 -> 乙方
                - 开发部们
                    - 技术总监
                        - 移动端开发
                            - 苹果
                            - 安卓
                            - H5
                        - PC端开发
                            - JAVA
                            - PHP
                            - .NET
                        - 后台开发  
                            - JAVA
                            - PHP
                            - .NET
                        - 产品
                            - 产品经理
                            - 产品专员
                        - UI
                            - UI妹子 UI汉子
                        - 测试
                            - 难缠
                    - 运营部 营销 或者推广

        - 一个app的诞生
                - 从无到有的过程
                - 新组建的团队
                - 甲方或者老板提出需求
                - 技术总监和产品经理 把甲方或者老板的想法前期可能就是一张A4
                - 产品经理 出原型
                - 技术研讨会 
                        - 看原型产品实施性
                - UI妹子 出效果图 标注图
                - 移动端 搭建框架
                - 服务器 模拟数据
                - 移动端和服务器
                            - code  0 成功 1 代表失败
                        {
                            code
                            message
                            data
                        }
                - 紧急会议
                        - 开发遇到问题 可能需要砍掉功能或者换种方式实现
                - 测试人员测试
                - 封板
                - 发布审核上线
                - 代码优化 版本迭代


        - 开发工具(团队开发)

                - bug处理
                    - JIRA
                    - bugfree
                - 代码管理
                    - SVN
                    - git
                        - 自己搭建git服务器
                        - 码云 天朝 （支持国货）
                            - 优点 中文
                                -创建私有项目免费
                                - 服务器在中国
                        - github
                                - 缺点: 收费 讨厌
                                - 创建私有项目收费
                        - 两种代码管理方式
                            - HTTPS
                                    - 不需要生成公钥和秘钥
                                    - 不安全 每次输入用户名密码 造成代码丢失
                            - SSH
                                    - 安全 
                                    - HTTPS的缺点就是他的优点

                                - 讲解
                                    - RSA 密钥  非对称加密 加密效率低
                                    - AES 秘钥  对称加密  加密效率高
                                        - 流程
                                            - 生成一个私钥和公钥
                                            - 把公钥非服务器
                                            - 随机生成一个AES秘钥
                                            - 通过私钥对AES秘钥加密
                                            - 把加密后的AES秘钥发送到服务器
                                            - 通过AES秘钥对项目加密
                                            - 服务器拿到加密后的AES秘钥 通过公钥解密
                                            - 服务器接收到通过AES加密后的项目
                                            - 服务器拿到解密后的AES 对加密的项目进行解密
                                            - 服务器帮我们保存项目

                    - 项目开发
                        - 模块确定
                            - 首页
                            - 消息
                            - 发现
                            - 我
                        - MVVM
                            - Model         
                            - View (view 和 VC)
                            - ViewModel
                                    - 帮助Vc减压
                                    - 帮助view减压
        - 上午内容回顾
                - 码云的使用
                - SSH 
                    - 需要程序员生成公钥和私钥
                - 在码云中创建一个项目
                - 克隆项目
                - 添加忽略文件
                - 项目框架
                    - 最低支持版本
                    - 类前缀
                    - 设置横竖屏 
                    - 设置图标 启动页
                    - 删除main.sb
                    - 创建项目文件夹
                            - Main
                            - Home
                            - Message
                            - Discover     
                            - Profile
                - UIImageRenderingMode 图片渲染方式
                - TintColor
        - git冲突问题
            - 团队开发
            - 有一份代码
                - A
                - B
        - 关于访客视图
                - 如果用户没有登录 四个子控制器 显示的为访客视图
                - 如果用户已经登录 四个子控制器 显示的列表
                    - 解决方式 创建一个基类 其他四个子类继承基类

        - 第三天内容总结
            - 搭建框架
            - 添加子控制器
                - 创建基类 （程序员偷懒）
                - 自定义visitorView
                    - SnapKit的使用
                    - 定义一个公共方法 供外界调用完成不同视图显示信息不同
                    - 设置圆圈动画
                    - Swift中 代理和协议的使用
                    - 使用闭包
                - 自定义tabbar
                    - 添加撰写按钮
                    - 通过遍历子控件完成控件布局
                    - 使用闭包
                - 自定义UIBarButtonItem
                        - Extension中使用便利构造函数
                        - 自定义SHBarButtonItem 使用重载构造函数

*/
